﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;

namespace Nsf.Samples.RetryActivitySample.WorkflowBase.Designer
{
    public class PropertySorter : ExpandableObjectConverter
    {
        #region Internal Classes

        private class PropertyOrderPair : IComparable<PropertyOrderPair>
        {
            /// <summary>
            /// Порядок следования свойства
            /// </summary>
            public Int32 Order { get; set;}
            /// <summary>
            /// Имя свойства
            /// </summary>
            public String Name { get; set;}

            public PropertyOrderPair(Int32 order, String name)
            {
                Name = name;
                Order = order;
            }

            #region IComparable<PropertyOrderPair> Members

            public int CompareTo(PropertyOrderPair other)
            {
                if (other == null)
                    return 1;

                var result = Order.CompareTo(other.Order);
                if (result == 0)
                    return Name.CompareTo(other.Name);
                return result;
            }

            #endregion
        }

        #endregion

        public override bool GetPropertiesSupported(ITypeDescriptorContext context)
        {
            return true;
        }

        public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
        {
            var propertyDescriptorCollection = TypeDescriptor.GetProperties(value, attributes);

            var propertyList = new List<PropertyOrderPair>(propertyDescriptorCollection.Count);
            foreach (PropertyDescriptor propertyDescriptor in propertyDescriptorCollection)
            {
                var attribute = propertyDescriptor.Attributes[typeof(PropertyOrderAttribute)] as PropertyOrderAttribute;
                var propertyOrder = attribute == null ? 0 : attribute.Order;
                propertyList.Add(new PropertyOrderPair(propertyOrder, propertyDescriptor.Name));
            }
            propertyList.Sort();
            var propertyNameList = propertyList.Select(obj => obj.Name).ToArray();
            return propertyDescriptorCollection.Sort(propertyNameList);
        }

    }

    [AttributeUsage(AttributeTargets.Property)]
    public class PropertyOrderAttribute : Attribute
    {
        public Int32 Order { get; protected set;}

        public PropertyOrderAttribute(Int32 order)
        {
            Order = order;
        }
    }
}
